package com.panshi.generate;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.lang.StringUtils;

import com.jfinal.kit.StrKit;

import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;

public class JavaSourceFactory {
    private static String SHOW_TABLE_NAME = "show tables";
    private static String SHOW_COLUNM_INFO = "desc ";

    public static void generateModels(Connection conn, String basePath, String packageName, String baseModelClass, String ModelSavePaht) {
        if (StrKit.isBlank(baseModelClass)) {
            baseModelClass = "com.jfinal.plugin.activerecord.Model";
        }
        @SuppressWarnings("deprecation")
        Configuration config = new Configuration();
        // 配置文件位置
        try {
            config.setDirectoryForTemplateLoading(new File(getTemplatePath()));
            Template template = config.getTemplate("entity.ftl");
            File entityFolder = new File(ModelSavePaht);
            if (!entityFolder.exists()) {
                entityFolder.mkdirs();
            }
            // 获取数据库中表信息
            System.out.println("****************欢迎使用JfinalModel生成工具****************");
            System.out.println("*****************正在获取该数据库中的表信息****************\r");
            PreparedStatement tableNamesPs = conn.prepareStatement(SHOW_TABLE_NAME);
            ResultSet tableInfoRs;
            tableInfoRs = tableNamesPs.executeQuery();
            while (tableInfoRs.next()) {
                // 获取表名
                String tn = tableInfoRs.getString(1);
                String primaryKey = "";
                System.out.println("\r\t\t加载：" + tn + "表信息成功");
                System.out.println("******************正在获取该表字段******************");
                // 根据表明查询该表中多字段
                PreparedStatement colunmsPs = conn.prepareStatement(SHOW_COLUNM_INFO + tn);
                List<String> colunms = new ArrayList<String>();
                ResultSet columnsRs = colunmsPs.executeQuery();
                // 获取对应表中的字段
                while (columnsRs.next()) {
                    String filed = columnsRs.getString(1);
                    String key = columnsRs.getString(4);
                    if (StringUtils.isNotEmpty(key) && StringUtils.equals(key, "PRI")) {
                        primaryKey = filed;
                    }
                    colunms.add(filed);
                }
                System.out.println("获取：" + tn + "表中字段成功,该表共" + colunms.size() + "个字段");
                EntityModel em = new EntityModel(packageName, baseModelClass, tn, primaryKey, toJavaClassStyle(tn), colunms);
                ConcurrentMap<String, EntityModel> modelMap = new ConcurrentHashMap<String, EntityModel>();
                modelMap.put("model", em);
                template.process(modelMap, new FileWriter(new File(ModelSavePaht + "\\" + em.getClassName() + ".java")));
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } catch (TemplateException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * Java类名风格字符串
     *
     * @param str
     * @return
     */
    private static String toJavaClassStyle(String str) {
        return underlineToCamelhump(str);
    }

    /**
     * 将下划线风格替换为驼峰风格 （首字母大写） eg：user_blog 转换成UserBlog
     *
     * @param str
     * @return
     */
    private static String underlineToCamelhump(String str) {
        Matcher matcher = Pattern.compile("_[a-z]").matcher(str);
        StringBuilder builder = new StringBuilder(str);
        for (int i = 0; matcher.find(); i++) {
            builder.replace(matcher.start() - i, matcher.end() - i, matcher.group().substring(1).toUpperCase());
        }
        builder.replace(0, 1, String.valueOf(Character.toUpperCase(builder.charAt(0))));
        return builder.toString();
    }

    private static String getTemplatePath() {
        String path = JavaSourceFactory.class.getResource("").getPath();
        return path;
    }

    public static void main(String[] args) {
        System.out.println(getTemplatePath());
    }
}